#include "JsonParser.h"
#include <gtest/gtest.h>

using namespace wj;

TEST(typetest, test_ok)
{
    auto v = JSONValue{};
    EXPECT_EQ(RetCode::OK, JSONParser::Parse(v, "null"));
    EXPECT_EQ(JSONType::JSON_NULL, v.GetType());
    EXPECT_EQ(RetCode::OK, JSONParser::Parse(v, "true"));
    EXPECT_EQ(JSONType::JSON_TRUE, v.GetType());
    EXPECT_EQ(RetCode::OK, JSONParser::Parse(v, "false"));
    EXPECT_EQ(JSONType::JSON_FALSE, v.GetType());
}

#define TEST_NUMBER(exp, str)                              \
    do                                                     \
    {                                                      \
        auto v = JSONValue{};                              \
        EXPECT_EQ(RetCode::OK, JSONParser::Parse(v, str)); \
        EXPECT_EQ(v.GetType(), JSONType::JSON_NUMBER);     \
        EXPECT_FLOAT_EQ(exp, v.GetNumber());               \
    } while (0)

TEST(numbertest, test_ok)
{
    TEST_NUMBER(0.0, "0");
    TEST_NUMBER(0.0, "-0");
    TEST_NUMBER(0.0, "-0.0");
    TEST_NUMBER(1.0, "1");
    TEST_NUMBER(-1.0, "-1");
    TEST_NUMBER(1.5, "1.5");
    TEST_NUMBER(-1.5, "-1.5");
    TEST_NUMBER(3.1416, "3.1416");
    TEST_NUMBER(1E10, "1E10");
    TEST_NUMBER(1e10, "1e10");
    TEST_NUMBER(1E+10, "1E+10");
    TEST_NUMBER(1E-10, "1E-10");
    TEST_NUMBER(-1E10, "-1E10");
    TEST_NUMBER(-1e10, "-1e10");
    TEST_NUMBER(-1E+10, "-1E+10");
    TEST_NUMBER(-1E-10, "-1E-10");
    TEST_NUMBER(1.234E+10, "1.234E+10");
    TEST_NUMBER(1.234E-10, "1.234E-10");
    TEST_NUMBER(0.0, "1e-10000");
}
#undef TEST_NUMBER

#define TEST_STRING(ret, exp, str)                       \
    do                                                   \
    {                                                    \
        auto v = JSONValue{};                            \
        EXPECT_EQ(ret, JSONParser::Parse(v, str));       \
        EXPECT_EQ(JSONType::JSON_STRING, v.GetType());   \
        EXPECT_STREQ(exp, v.Get<std::string>().c_str()); \
    } while (0)

#define TEST_STRING_ERROR(err, str)                \
    do                                             \
    {                                              \
        auto v = JSONValue{};                      \
        EXPECT_EQ(err, JSONParser::Parse(v, str)); \
    } while (0)

TEST(stringtest, test_ok)
{
    TEST_STRING(RetCode::OK, "", "\"\"");
    TEST_STRING(RetCode::OK, "Hello", "\"Hello\"");
    TEST_STRING(RetCode::OK, "Hello\nWorld", "\"Hello\\nWorld\"");
    TEST_STRING(RetCode::OK,
                "\" \\ / \b \f \n \r \t",
                "\"\\\" \\\\ \\/ \\b \\f \\n \\r \\t\"");
}

TEST(stringtest, invalid_escape)
{
    TEST_STRING_ERROR(RetCode::PARSE_INVALID_STRING_ESCAPE, "\"\\v\"");
    TEST_STRING_ERROR(RetCode::PARSE_INVALID_STRING_ESCAPE, "\"\\'\"");
    TEST_STRING_ERROR(RetCode::PARSE_INVALID_STRING_ESCAPE, "\"\\0\"");
    TEST_STRING_ERROR(RetCode::PARSE_INVALID_STRING_ESCAPE, "\"\\x12\"");
}

TEST(stringtest, invalid_char)
{
    TEST_STRING_ERROR(RetCode::PARSE_INVALID_STRING_CHAR, "\"\x01\"");
    TEST_STRING_ERROR(RetCode::PARSE_INVALID_STRING_CHAR, "\"\x1F\"");
}

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}